package com.learning.spring.security.base.config;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy;

/**
 * ClassName: SecurityConfiguration
 * Description: 会话管理
 * Date: 2022/7/4 10:17
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class SessionManagementConfiguration {

    @Bean
    SessionFixationProtectionStrategy fixationProtectionStrategy() {
        return new SessionFixationProtectionStrategy();
    }

    @Bean
    UsernamePasswordAuthenticationFilter authenticationFilter() {
        UsernamePasswordAuthenticationFilter authenticationFilter = new UsernamePasswordAuthenticationFilter();
        authenticationFilter.setSessionAuthenticationStrategy(fixationProtectionStrategy());
        return authenticationFilter;
    }

    @Bean
    public SecurityFilterChain myFilterChain(HttpSecurity http) throws Exception {
        http.addFilterAt(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .sessionManagement(session ->
                        session.sessionAuthenticationStrategy(fixationProtectionStrategy())
                );
        return http.build();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.sessionManagement(session ->
                session
                        // 新建 Session，防止会话截止攻击
                        .sessionFixation(SessionManagementConfigurer.SessionFixationConfigurer::newSession)
                        //
                        .sessionAuthenticationErrorUrl("/sessionAuthenticationErrorUrl.html")
                        // 创建会话策略
                        .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
                        // 会话超时后的重定向页面
                        .invalidSessionUrl("/invalidSession.htm")
                        // 会话并发控制的多少
                        .maximumSessions(1)
                        // 单态登录中，避免第二次登录
                        .maxSessionsPreventsLogin(true)
        );
        return http.build();
    }
}
